package com.tms.gateway.config;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaHttpMethod;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.tms.gateway.service.PermissionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;

/**
 * Author：潘建冰
 * Package：com.tms.gateway.config
 * Project：TaskManageSystem
 * name：SaTokenConfigure
 * Date：2025/3/26  13:25
 */
@Configuration
@Slf4j
public class SaTokenConfigure {

    @Autowired
    private PermissionService permissionService;

    // 注册 Sa-Token全局过滤器
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截地址
                .addInclude("/**")
                // 开放地址
                .addExclude("/api/user/loginByUserName")
                .addExclude("/api/user/loginByPhone")
                .addExclude("/api/user/register")
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    // 获取当前请求路径和方法
                    String requestPath = SaHolder.getRequest().getRequestPath();
                    // 过滤掉/api
                    requestPath = requestPath.startsWith("/api/") ? requestPath.substring(4) : requestPath;
                    String requestMethod = SaHolder.getRequest().getMethod();
                    // 获取当前登录用户ID
                    String userId = StpUtil.getLoginIdAsString();
                    // 调用权限服务进行权限验证
                    boolean hasPermission = permissionService.checkPermission(requestPath, requestMethod, userId);
                    if (!hasPermission) {
                        throw new RuntimeException("没有访问权限");
                    }
                    log.info("网关拦截：请求接口{}, 请求方法{}, 鉴权已通过",requestPath,requestMethod);
                })
                // 异常处理方法：每次setAuth函数出现异常时进入
                .setError(e -> {
                    // 设置错误返回格式为JSON
                    ServerWebExchange exchange = SaReactorSyncHolder.getContext();
                    exchange.getResponse().getHeaders().set("Content-Type", "application/json; charset=utf-8");
                    return SaResult.error(e.getMessage());
                })
                .setBeforeAuth(obj -> {
                    // ---------- 设置跨域响应头 ----------
                    SaHolder.getResponse()
                            // 允许指定域访问跨域资源
                            .setHeader("Access-Control-Allow-Origin", "*")
                            // 允许所有请求方式
                            .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
                            // 有效时间
                            .setHeader("Access-Control-Max-Age", "3600")
                            // 允许的header参数
                            .setHeader("Access-Control-Allow-Headers", "*");

                    // 如果是预检请求，则立即返回到前端
                    SaRouter.match(SaHttpMethod.OPTIONS)
                            .free(r -> System.out.println("--------OPTIONS预检请求，不做处理"))
                            .back();
                });
    }
}
